package com.yydream.common.config;

import com.yydream.common.filters.JwtAuthenticationTokenFilter;
import com.yydream.common.handler.CustomAccessDeniedHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private CustomAccessDeniedHandler customAccessDeniedHandler;

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * Override this method to configure the {@link HttpSecurity}. Typically subclasses
     * should not invoke this method by calling super as it may override their
     * configuration. The default configuration is:
     *
     * <pre>
     * http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
     * </pre>
     * <p>
     * Any endpoint that requires defense against common vulnerabilities can be specified
     * here, including public ones. See {@link HttpSecurity#authorizeRequests} and the
     * `permitAll()` authorization rule for more details on public endpoints.
     *
     * @param httpSecurity the {@link HttpSecurity} to modify
     * @throws Exception if an error occurs
     */
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {

        //CSRF禁用，因为不使用session
        httpSecurity.csrf().disable()
        //基于token，所以不需要session
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        //授权请求
        .authorizeRequests()
        //对于登录login 允许匿名访问
        .antMatchers(
                "/css/**",
                "/images/**",
                "/files/**",
                "**.js",
                "/webjars/**",
                "/v2/**",
                "/doc.html",
                "/api-docs",
                "/api-docs-ext",
                "/swagger-ui.html",
                "/swagger-resources/**",
                "/common/login",
                "/common/register",
                "/common/captcha",
                "/common/forgot",
                "/ws/**",
                "/test/**"
        ).anonymous()
        //除上面所有请求都要鉴权认证
        .anyRequest().authenticated();

        // 添加JWT filter 到 UsernamePasswordAuthenticationFilter 之前
        httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

//        允许跨域
        httpSecurity.cors();

//        处理403
        httpSecurity.exceptionHandling().authenticationEntryPoint(customAccessDeniedHandler);

    }

}
